package com.geek.controller;

import com.geek.aliyun.GeekAliyunClient;
import com.geek.bean.SmsSendResult;
import com.geek.bean.BaseRespVo;
import com.geek.bean.vo.LoginInfoVo;
import com.geek.bean.vo.RegCaptchaVo;
import com.geek.bean.vo.RegisterInfoVo;
import com.geek.bean.vo.ResetVo;
import com.geek.model.MarketUser;
import com.geek.service.SmsService;
import com.geek.service.UserService;
import com.geek.util.Md5Util;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("wx/auth")
public class WxAuthController {

    @Autowired
    UserService userService;
    @Autowired
    GeekAliyunClient geekAliyunClient;
    @Autowired
    SmsService smsService;

    static Map<String, Long> lastTimeMap;

    static {
        lastTimeMap = new HashMap<>();
        lastTimeMap.put("lastTime", 0L);
    }

    String code;

    @PostMapping("login")
    public BaseRespVo login(@Valid @RequestBody LoginInfoVo loginInfoVo) {
        String username = loginInfoVo.getUsername();
        String password = loginInfoVo.getPassword();
        String encryptPwd = Md5Util.getMd5(password, username);
        Subject subject = SecurityUtils.getSubject();
        // username用来给realm查询credentials
        // password用来和查询出来的credentials做比较 → 如果比较成功 → isAuthenticated=true
        try {
            subject.login(new UsernamePasswordToken(username, encryptPwd));
        } catch (IncorrectCredentialsException e) {
            e.printStackTrace();
            return BaseRespVo.fail(500, "密码错误");
        } catch (AuthenticationException e) {
            e.printStackTrace();
            return BaseRespVo.fail(500, "账号不存在");
        }
        boolean authenticated = subject.isAuthenticated();
        //登录成功
        if (authenticated) {
            // 在认证(登录)成功的情况下 可以获取用户信息 → realm中doGetAuthenticationInfo中的返回的simpleAuthenticationInfo中的第一个参数
            // 存的是user的id，那么取出来的也是user的id
            Integer userId = (Integer) subject.getPrincipal();
            MarketUser marketUser = userService.findById(userId);
            //更新登录时间
            userService.updateLoginTime(userId);
            HashMap<String, Object> data = new HashMap<>();
            // 返回SessionId → 小程序的其他请求就会携带这个SessionId过来
            data.put("token", subject.getSession().getId());
            HashMap<String, String> userInfo = new HashMap<>();
            userInfo.put("nickName", marketUser.getNickname());
            userInfo.put("avatarUrl", marketUser.getAvatar());
            data.put("userInfo", userInfo);
            return BaseRespVo.ok(data);
        }
        return BaseRespVo.ok("token");
    }

    @PostMapping("logout")
    public BaseRespVo logout() {
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return BaseRespVo.ok();

    }

    @PostMapping("regCaptcha")
    public BaseRespVo regCaptcha(@Valid @RequestBody RegCaptchaVo regCaptchaVo) {
        //获取请求参数
        String mobile = regCaptchaVo.getMobile();
        //上次发送验证时间戳
        long lastTime = lastTimeMap.get("lastTime");
        Date current = new Date();
        // 发送间隔时长
        long timeInterval = current.getTime() - lastTime;
        //判断发送间隔是否超过1分钟
        if (lastTime == 0L || timeInterval >= 60000L) {
            SmsSendResult smsSendResult = smsService.sendValidationCode(mobile);
            this.code = smsSendResult.getCode();
            lastTimeMap.clear();
            lastTimeMap.put("lastTime", current.getTime());
            boolean noMobile = smsSendResult.getJsonResult().contains("手机号码格式");
            //判断手机号码是否存在
            if (noMobile) {
                return BaseRespVo.fail(500, "手机号码不存在");
            }
            return BaseRespVo.ok();
        } else {
            return BaseRespVo.fail(500, "发送间隔未超过1分钟");
        }
    }

    @PostMapping("register")
    public BaseRespVo register(@Valid @RequestBody RegisterInfoVo registerInfoVo) {
        //判断验证码是否正确
//        if (!registerInfoVo.getCode().equals(this.code)) {
//            return BaseRespVo.fail(500, "验证码错误");
//        }
        //上次发送验证时间戳
        long lastTime = lastTimeMap.get("lastTime");
        Date current = new Date();
        // 发送间隔时长
        long timeInterval = current.getTime() - lastTime;
        //判断验证码是否有效
        if (timeInterval >= 20000L) {
            //设置有效时间为10s，方便测试
            return BaseRespVo.fail(500, "验证码已过期");
        }
        //判断手机号是否已注册
        int result = userService.create(registerInfoVo);
        if (result == 1) {
            //手机号已注册过
            return BaseRespVo.fail(500, "手机号已注册过");
        }
        if (result == 2) {
            //用户名已存在
            return BaseRespVo.fail(500, "用户名已存在");
        }
        //注册成功,获取登录信息
        String password = registerInfoVo.getPassword();
        String username = registerInfoVo.getUsername();
        String encryptPwd = Md5Util.getMd5(password, username);
        Subject subject = SecurityUtils.getSubject();
        subject.login(new UsernamePasswordToken(username, encryptPwd));

        Integer userId = (Integer) subject.getPrincipal();
        MarketUser marketUser = userService.findById(userId);
        //更新登录时间
        userService.updateLoginTime(userId);
        //封装返回数据
        HashMap<String, String> userInfo = new HashMap<>();
        userInfo.put("nickName", marketUser.getNickname());
        userInfo.put("avatarUrl", marketUser.getAvatar());
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("token", subject.getSession().getId());
        dataMap.put("userInfo", userInfo);

        return BaseRespVo.ok(dataMap);
    }

    @PostMapping("reset")
    public BaseRespVo reset(@Valid @RequestBody ResetVo resetVo) {

        //验证验证码
//        if (!resetVo.getCode().equals(this.code)) {
//            return BaseRespVo.fail(703, "验证码错误");
//        }
        //上次发送验证时间戳
        long lastTime = lastTimeMap.get("lastTime");
        Date current = new Date();
        // 发送间隔时长
        long timeInterval = current.getTime() - lastTime;
        //判断验证码是否有效
        if (timeInterval >= 10000L) {
            //设置有效时间为10s，方便测试
            return BaseRespVo.fail(500, "验证码已过期");
        }
        //查询账号
        int result = userService.findByMobile(resetVo.getMobile());
        if (result != 1) {
            //账号不存在
            return BaseRespVo.fail(500, "账号不存在,请注册");
        }
        //修改密码
        userService.modifyPassword(resetVo.getMobile(), resetVo.getPassword());
        return BaseRespVo.ok();
    }

    @GetMapping("unAuthc")
    public BaseRespVo unAuthc() {
        return BaseRespVo.unAuthc();
    }
}
